import os
from typing import List, Optional, Dict
import numpy as np
import cv2
from PyQt5.QtCore import QObject, pyqtSignal

from models.data_models import ImageInfo

class ImageProcessor(QObject):
    """图像处理组件"""

    # 信号定义
    image_loaded = pyqtSignal(str)  # 图像加载完成信号
    batch_loaded = pyqtSignal(int)  # 批量加载完成信号

    def __init__(self):
        super().__init__()
        self.image_queue: List[ImageInfo] = []
        self.current_index: int = -1
        self.supported_formats = {'.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.tif'}

    def load_image(self, image_path: str) -> Optional[np.ndarray]:
        """加载单张图像"""
        if not os.path.isfile(image_path):
            print(f"图像文件不存在: {image_path}")
            return None

        image = cv2.imread(image_path)
        if image is None:
            print(f"无法读取图像: {image_path}")
            return None

        image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        height, width = image.shape[:2]
        filename = os.path.basename(image_path)

        image_info = ImageInfo(
            path=image_path,
            filename=filename,
            size=(width, height)
        )

        # 避免重复添加
        for idx, img in enumerate(self.image_queue):
            if img.path == image_path:
                self.current_index = idx
                break
        else:
            self.image_queue.append(image_info)
            self.current_index = len(self.image_queue) - 1

        self.image_loaded.emit(image_path)
        return image_rgb

    def load_batch(self, folder_path: str) -> List[str]:
        """批量加载文件夹中的图像"""
        if not os.path.isdir(folder_path):
            print(f"文件夹不存在: {folder_path}")
            return []

        loaded_paths = []
        files = sorted(os.listdir(folder_path))  # 保证顺序一致

        for filename in files:
            file_path = os.path.join(folder_path, filename)
            _, ext = os.path.splitext(filename.lower())
            if os.path.isfile(file_path) and ext in self.supported_formats:
                image = cv2.imread(file_path)
                if image is not None:
                    height, width = image.shape[:2]
                    image_info = ImageInfo(
                        path=file_path,
                        filename=filename,
                        size=(width, height)
                    )
                    if not any(img.path == file_path for img in self.image_queue):
                        self.image_queue.append(image_info)
                        loaded_paths.append(file_path)
                else:
                    print(f"跳过无效图像: {filename}")

        if loaded_paths and self.current_index == -1:
            self.current_index = 0

        self.batch_loaded.emit(len(loaded_paths))
        return loaded_paths

    def get_current_image(self) -> Optional[np.ndarray]:
        """获取当前图像"""
        image_info = self.get_current_image_info()
        if image_info and os.path.isfile(image_info.path):
            image = cv2.imread(image_info.path)
            if image is not None:
                return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        return None

    def get_current_image_info(self) -> Optional[ImageInfo]:
        """获取当前图像信息"""
        if 0 <= self.current_index < len(self.image_queue):
            return self.image_queue[self.current_index]
        return None

    def set_current_index(self, index: int) -> bool:
        """设置当前图像索引"""
        if 0 <= index < len(self.image_queue):
            self.current_index = index
            return True
        return False

    def get_image_by_index(self, index: int) -> Optional[np.ndarray]:
        """根据索引获取图像"""
        if 0 <= index < len(self.image_queue):
            image_info = self.image_queue[index]
            if os.path.isfile(image_info.path):
                image = cv2.imread(image_info.path)
                if image is not None:
                    return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        return None

    def clear_queue(self):
        """清空图像队列"""
        self.image_queue.clear()
        self.current_index = -1

    def get_queue_info(self) -> Dict[str, int]:
        """获取队列信息"""
        return {
            "total_images": len(self.image_queue),
            "current_index": self.current_index,
            "processed_count": sum(1 for img in self.image_queue if getattr(img, "is_processed", False))
        }
